Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

module: improve error message for top-level await in CommonJS #55874

Open
wants to merge 23 commits into
base: main
Choose a base branch
from

Conversation

mertcanaltin
Copy link
Member

Added a specific error message for using top-level await in CommonJS modules. The error now suggests using ESM or wrapping await in an async function for clarity.

Fixes: #55776

@nodejs-github-bot nodejs-github-bot added c++ Issues and PRs that require attention from people who are familiar with C++. needs-ci PRs that need a full CI run. vm Issues and PRs related to the vm subsystem. labels Nov 15, 2024
Copy link

codecov bot commented Nov 15, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 88.53%. Comparing base (4ee87b8) to head (01b4b6d).
Report is 72 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main   #55874      +/-   ##
==========================================
+ Coverage   88.00%   88.53%   +0.53%     
==========================================
  Files         656      657       +1     
  Lines      189000   189866     +866     
  Branches    35995    36453     +458     
==========================================
+ Hits       166320   168092    +1772     
+ Misses      15840    14981     -859     
+ Partials     6840     6793      -47     
Files with missing lines Coverage Δ
src/node_contextify.cc 81.66% <100.00%> (+0.29%) ⬆️

... and 125 files with indirect coverage changes

Copy link
Member

@GeoffreyBooth GeoffreyBooth left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for tackling this! I’d love to see this issue addressed.

src/node_contextify.cc Outdated Show resolved Hide resolved
Comment on lines 1821 to 1828
for (const auto& error_message : throws_only_in_cjs_error_messages) {
if (message_view.find(error_message) != std::string_view::npos) {
isolate->ThrowException(v8::Exception::SyntaxError(
String::NewFromUtf8(
isolate,
"Top-level await is not supported in CommonJS. "
"Consider using ESM or wrap await in an async function.")
.ToLocalChecked()));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems like this message is being printed for any of the “throws only in CJS” error messages? I would think that we would want to print this only when the user wrote a top-level await in a file that didn’t parse successfully as ESM.

Also in general our messages don’t use “ESM” as that’s not a widely known term. I think we usually write “module syntax” or “import/export syntax”.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thank you very much for the improvement suggestions, I wonder if you could comment on the broken test/es-module/test-esm-detect-ambiguous.mjs tests, I am trying to improve them

in addition, I wonder if it would be better to include my newly added test/parallel/test-commonjs-top-level-await.js test in test-esm-detect-ambiguous.mjs

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What test failure do you see?

in addition, I wonder if it would be better to include my newly added test/parallel/test-commonjs-top-level-await.js test in test-esm-detect-ambiguous.mjs

Yes, my preference would be to keep all the syntax detection tests together. If you could follow the pattern of the other related tests that would be great.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I saw this
nodejs/node/actions/runs/11863231944/job/33064268346?pr=55874

I don't see the failure in this output. When you run the tests locally, what fails?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

when I run the tests locally:
./node test/es-module/test-esm-detect-ambiguous.mjs

I see that 7 tests are exploding, I think the code we do error handling is crushing the expectations here

failing tests:

✖ does not warn when there are no package.json
✖ permits declaration of CommonJS module variables
✖ throws on undefined require when top-level await triggers ESM parsing
✖ still throws on await in an ordinary sync function
✖ permits top-level await above import/export syntax
✖ reports unfinished top-level await
✖ permits top-level await

I'm trying to fix this place.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@GeoffreyBooth would you have any suggestions for these test failures?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think those failures are probably legit and the implementation needs to be adjusted so that they pass.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think those failures are probably legit and the implementation needs to be adjusted so that they pass.

thank you, as you said I will try to fix the tests as legitimate

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I made an update for this place, many thanks for the suggestions @GeoffreyBooth

@mertcanaltin mertcanaltin added the help wanted Issues that need assistance from volunteers or PRs that need help to proceed. label Nov 27, 2024
@mertcanaltin mertcanaltin force-pushed the dev-55776 branch 2 times, most recently from 3dccce9 to 76f87e4 Compare November 29, 2024 21:18
@mertcanaltin mertcanaltin added review wanted PRs that need reviews. and removed help wanted Issues that need assistance from volunteers or PRs that need help to proceed. labels Nov 30, 2024
Copy link
Member

@GeoffreyBooth GeoffreyBooth left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for taking another pass at this. I mention this in the particular notes, but in general:

  1. Please don't change lines based on personal preference or readability. We value the ability for git blame to point directly to the commit/PR that added or meaningfully changed a particular line, and that ability is diluted when unrelated PRs rewrite lines of code.

  2. Very few, if any, tests should change as a result of your PR: only tests specifically related to top-level await in CommonJS. Any other tests that fail as a result of your changes mean that there's a bug in the implementation that needs to be addressed. My guess is that the bug is that the new code isn't checking that the error message being thrown is specifically about top-level await. If there aren't currently tests for top-level await in CommonJS and your new error message, one or more should be added.

This is close; another pass and I think you may get it there. Thanks for your effort!

src/node_contextify.cc Outdated Show resolved Hide resolved
src/node_contextify.cc Outdated Show resolved Hide resolved
test/es-module/test-esm-detect-ambiguous.mjs Outdated Show resolved Hide resolved
test/es-module/test-esm-detect-ambiguous.mjs Outdated Show resolved Hide resolved
test/es-module/test-esm-detect-ambiguous.mjs Outdated Show resolved Hide resolved
test/es-module/test-esm-detect-ambiguous.mjs Outdated Show resolved Hide resolved
test/es-module/test-esm-detect-ambiguous.mjs Outdated Show resolved Hide resolved
test/es-module/test-esm-detect-ambiguous.mjs Outdated Show resolved Hide resolved
test/es-module/test-esm-detect-ambiguous.mjs Outdated Show resolved Hide resolved
test/es-module/test-esm-detect-ambiguous.mjs Outdated Show resolved Hide resolved
@mertcanaltin
Copy link
Member Author

Thanks for taking another pass at this. I mention this in the particular notes, but in general:

  1. Please don't change lines based on personal preference or readability. We value the ability for git blame to point directly to the commit/PR that added or meaningfully changed a particular line, and that ability is diluted when unrelated PRs rewrite lines of code.
  2. Very few, if any, tests should change as a result of your PR: only tests specifically related to top-level await in CommonJS. Any other tests that fail as a result of your changes mean that there's a bug in the implementation that needs to be addressed. My guess is that the bug is that the new code isn't checking that the error message being thrown is specifically about top-level await. If there aren't currently tests for top-level await in CommonJS and your new error message, one or more should be added.

This is close; another pass and I think you may get it there. Thanks for your effort!

thank you very much for the review, I will be sending a new commit following what you said

@mertcanaltin
Copy link
Member Author

Greetings, when I did as you suggested to cover only the top level error, I saw that all tests passed except 1 test

Copy link
Member

@GeoffreyBooth GeoffreyBooth left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, this is much better. What’s the one test that is failing?

test/es-module/test-esm-detect-ambiguous.mjs Outdated Show resolved Hide resolved

match(
stderr,
/await is only valid in async functions and the top level bodies of modules/
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The assertion should include some of the new text you’re adding, such as “To use top-level await,” to verify that your new error message is what’s getting printed.

@GeoffreyBooth GeoffreyBooth added module Issues and PRs related to the module subsystem. esm Issues and PRs related to the ECMAScript Modules implementation. labels Dec 2, 2024
@mertcanaltin
Copy link
Member Author

Thanks, this is much better. What’s the one test that is failing?

I saw wrong, all the tests passed my local. 🙏

@GeoffreyBooth
Copy link
Member

I saw wrong, all the tests passed my local. 🙏

There’s a test failing in here, in the relevant file: https://github.com/nodejs/node/actions/runs/12133213207/job/33828380981?pr=55874

@cjihrig why isn’t the CI output showing me which test is failing within that file?

@cjihrig
Copy link
Contributor

cjihrig commented Dec 3, 2024

why isn’t the CI output showing me which test is failing within that file?

No clue. But the output is incomplete. There is no summary at the end either. It looks like maybe the Python runner killed the Node process or otherwise truncated its output.

@cjihrig
Copy link
Contributor

cjihrig commented Dec 3, 2024

@GeoffreyBooth just FYI - IIRC, you asked me a similar question in Slack last year. There was output truncated only in GitHub Actions. Then you asked me to find a test run where truncation was happening without the use of node:test, and I did. I believe @MoLow was a part of that thread as well.

@GeoffreyBooth
Copy link
Member

IIRC, you asked me a similar question in Slack last year.

Yes, last August: https://openjs-foundation.slack.com/archives/C019Y2T6STH/p1691860008875109. I’m lucky if I can remember last month, much less last year. Sorry to repeat. I also opened #49120 but that got closed.

@mertcanaltin
Copy link
Member Author

I saw wrong, all the tests passed my local. 🙏

There’s a test failing in here, in the relevant file: https://github.com/nodejs/node/actions/runs/12133213207/job/33828380981?pr=55874

@cjihrig why isn’t the CI output showing me which test is failing within that file?

yes, ı view my local enviorement this test is fail

test at test/es-module/test-esm-detect-ambiguous.mjs:367:5
 does not warn when there are no package.json (63.625667ms)
  AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:
  + actual - expected
  
  + "(node:18411) [MODULE_TYPELESS_PACKAGE_JSON] Warning: Module type of file:///Users/mert/Desktop/openSource/node/test/fixtures/es-modules/loose.js is not specified and it doesn't parse as CommonJS.\n" +
  +   'Reparsing as ES module because module syntax was detected. This incurs a performance overhead.\n' +
  +   'To eliminate this warning, add "type": "module" to /Users/mert/package.json.\n' +
  +   '(Use `node --trace-warnings ...` to show where the warning was created)\n'
  - ''
  
      at TestContext.<anonymous> (file:///Users/mert/Desktop/openSource/node/test/es-module/test-esm-detect-ambiguous.mjs:372:7)
      at process.processTicksAndRejections (node:internal/process/task_queues:105:5)
      at async Test.run (node:internal/test_runner/test:932:9)
      at async Promise.all (index 3)
      at async Suite.run (node:internal/test_runner/test:1310:7)
      at async Promise.all (index 6)
      at async Suite.run (node:internal/test_runner/test:1310:7)
      at async startSubtestAfterBootstrap (node:internal/test_runner/harness:297:3) {
    generatedMessage: true,
    code: 'ERR_ASSERTION',
    actual: '(node:18411) [MODULE_TYPELESS_PACKAGE_JSON] Warning: Module type of file:///Users/mert/Desktop/openSource/node/test/fixtures/es-modules/loose.js is not specified and it doesn\'t parse as CommonJS.\nReparsing as ES module because module syntax was detected. This incurs a performance overhead.\nTo eliminate this warning, add "type": "module" to /Users/mert/package.json.\n(Use `node --trace-warnings ...` to show where the warning was created)\n',
    expected: '',
    operator: 'strictEqual'
  }

@mertcanaltin
Copy link
Member Author

greetings I tried to make the error message more descriptive, in addition I tried to throw it when there is a file that cannot be successfully parsed as ESM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
c++ Issues and PRs that require attention from people who are familiar with C++. esm Issues and PRs related to the ECMAScript Modules implementation. module Issues and PRs related to the module subsystem. needs-ci PRs that need a full CI run. review wanted PRs that need reviews. vm Issues and PRs related to the vm subsystem.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

detect-module: confusing error when parsing a CommonJS module with top-level await
4 participants